﻿using GameBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace VCity
{
    public class AdsBoardManager : MonoSingleton<AdsBoardManager>
    {
        public bool updateGroup;
        public bool updateName;

        [Space]
        public List<AdsBoardGroup> adsGroups;

        public float interactDistance = 30f;

        [Header("Config")]
        public bool coroutineUpdate;

        private void OnValidate()
        {
            if (updateGroup)
            {
                updateGroup = false;

                // temp dic[string, group]
                var dic = adsGroups.ToDictionary(g => {
                    g.boards.Clear();
                    return g.name;
                });

                AdsBoard[] finds = FindObjectsOfType<AdsBoard>();
                Debug.Log($"Total boards: {finds.Length}");
                for (int i = 0, length = finds.Length; i < length; i++)
                {
                    var a = finds[i];
                    int index = a.name.IndexOf('-');
                    if (index > 0)
                    {
                        string district = a.name[..index];
                        //Debug.Log($"Distrct {district}");
                        if (!dic.TryGetValue(district, out var group))
                        {
                            Debug.Log($"New district: {district}");
                            group = new AdsBoardGroup()
                            {
                                name = district,
                                boards = new List<AdsBoard>()
                            };
                            adsGroups.Add(group);

                            dic[district] = group;
                        }

                        group.boards.Add(a);
                        //a.name = $"{district}-{group.boards.Count}";
                    }
                }

                adsGroups.Sort((a, b) => a.name.CompareTo(b.name));
            }

            if (updateName)
            {
                updateName = false;

                for (int i = 0, length = adsGroups.Count; i < length; i++)
                {
                    var group = adsGroups[i];
                    for (int j = 0, boardCount = group.boards.Count; j < boardCount; j++)
                    {
                        var a = group.boards[j];
                        a.name = $"{group.name}-{j + 1}";
                    }
                }
            }
        }

        private void Update()
        {
            //TODO: check and remove destroyed board

            // webgl audio
            ForeachBoard(board =>
            {
                var charPos = ClientMain.Instance.charCtrl.transform.position;
                board.UpdateVideoPlayerAudioGL(charPos);
            });
        }

        public void OnAdsDataUpdate()
        {
            if (coroutineUpdate)
                StartCoroutine(UpdateAdsBoards());
            else
            {
                ForeachBoard(board =>
                {
                    var res = GameResources.Instance;
                    if (res.adsDic.TryGetValue(board.name, out var data))
                        board.SetData(data);
                });
            }
        }

        IEnumerator UpdateAdsBoards()
        {
            var res = GameResources.Instance;
            foreach (var group in adsGroups)
            {
                var boards = group.boards;
                for (int i = 0, length = boards.Count; i < length; i++)
                {
                    var board = boards[i];
                    if (res.adsDic.TryGetValue(board.name, out var data))
                        board.SetData(data);
                    yield return null;
                }
            }
        }

        void ForeachBoard(Action<AdsBoard> act)
        {
            for (int i = 0, length = adsGroups.Count; i < length; i++)
            {
                var boards = adsGroups[i].boards;
                for (int j = 0, boardCount = boards.Count; j < boardCount; j++)
                {
                    act(boards[j]);
                }
            }
        }
    }

    [System.Serializable]
    public struct AdsBoardGroup
    {
        public string name;
        public List<AdsBoard> boards;
    }
}